/*
 * File:   main.cpp
 * Author: cyril
 *
 * Created on 10 décembre 2012, 09:33
 */
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "const.h"

using namespace std;


/*
 *  INITIALISATION DE LA PLAQUE
 */
int** initPlaque() {

    int **plaque;
    // Allocation du tableau
    plaque = new int*[HAUTEUR];
    for (int i = 0; i < HAUTEUR; ++i)
        plaque[i] = new int[LONGUEUR];


    int i, j;
    int cpt = 0;

    for (i = 0; i < HAUTEUR; i++) {
        for (j = 0; j < LONGUEUR; j++) {
            plaque[i][j] = cpt;
            cpt++;
        }
    }

    return plaque;
}

int** initVoisin(int** plaque) {
    int **voisins;

    // Allocation du tableau
    voisins = new int*[NBPLAQUE];
    for (int i = 0; i < NBPLAQUE; ++i)
        voisins[i] = new int[NBVOISINS];

    for (int i = 0; i < NBPLAQUE; i++) {
        for (int j = 0; j < NBVOISINS; j++) {
            voisins[i][j] = -1;
        }
    }
    // Remplissage des voisins
    for (int i = 0; i < HAUTEUR; i++) {
        for (int j = 0; j < LONGUEUR; j++) {

            if (i > 0) // NORD
                voisins[plaque[i][j]][0] = plaque[i - 1][j];
            if ((i > 0) && (j < LONGUEUR - 1)) // NORD EST
                voisins[plaque[i][j]][1] = plaque[i - 1][j + 1];
            if (j < LONGUEUR - 1) // EST
                voisins[plaque[i][j]][2] = plaque[i][j + 1];
            if ((i < HAUTEUR - 1) && (j < LONGUEUR - 1)) // SUD EST
                voisins[plaque[i][j]][3] = plaque[i + 1][j + 1];
            if (i < HAUTEUR - 1) // SUD
                voisins[plaque[i][j]][4] = plaque[i + 1][j];
            if ((i < HAUTEUR - 1) && (j > 0)) // SUD OUEST
                voisins[plaque[i][j]][5] = plaque[i + 1][j - 1];
            if (j > 0)// OUEST
                voisins[plaque[i][j]][6] = plaque[i][j - 1];
            if ((i > 0) && (j > 0))// NORD OUEST
                voisins[plaque[i][j]][7] = plaque[i - 1][j - 1];


        }
    }

    return voisins;
}

int main(int argc, char* argv []) {
    int i, compteur;
    MPI_Status etat;
    // Chemin absolu
    // Jeremy :
   
    char *cmds[2] = {
        "/home/bouh/programmation-parallele-gres-navarro/calculateur",
        "/home/bouh/programmation-parallele-gres-navarro/coordinateur"
    };
    
    // Cyril
   /* char *cmds[2] = {
        "/home/cyril/NetBeansProjects/ProgParallele/calculateur",
        "/home/cyril/NetBeansProjects/ProgParallele/coordinateur"
    };
*/
    int np[2] = {NBPLAQUE, 1};

    int** plaque = initPlaque();

  /*  for (i = 0; i < HAUTEUR; i++) {
        for (int j = 0; j < LONGUEUR; j++) {
            printf("Plaque N° %d \n", plaque[i][j]);
        }
    }*/


    int** voisins = initVoisin(plaque);

   /* for (i = 0; i < NBPLAQUE; i++) {
        printf("Calculateur %d : ",i);
        for (int j = 0; j < NBVOISINS; j++) {
            printf("%d,", voisins[i][j]);
        }
        printf("\n");
    }*/


    // initialisation de la temperature
    float temperatures[NBPLAQUE] = { 20, 20, 20, 20, 20,50, 20, 20, 20, 20, 20, 20};
  /*  for (i = 0; i < NBPLAQUE; i++) {
       /* if(i==5){
            temperatures[i]=100.0;
        }
        else{*/
         //   temperatures[i]=rand() % 1000 + 1;
       /*}
    }*/
    // Pas d'info supplémentaires pour contrôler le lancement
    // des programmes 1 et 2
    MPI_Info infos[2] = {MPI_INFO_NULL, MPI_INFO_NULL};
    int errcodes[NBPROCESS]; // Les codes de retours des 5 processus

    MPI_Comm intercomm; // L'espace de communication père - fils
    MPI_Init(&argc, &argv);
    // On lance simultanément 2 instances de prg1 et 3 de prg2
    MPI_Comm_spawn_multiple(
            2,
            cmds,
            MPI_ARGVS_NULL,
            np,
            infos,
            0,
            MPI_COMM_WORLD,
            &intercomm,
            errcodes
            );
    printf("Pere   : J'ai lance toutes les instances.\n");
  
    // Envoi synchrone aux calculateurs
    for (i = 0; i < NBPLAQUE; i++) {
        MPI_Send(voisins[i],NBVOISINS, MPI_INT, i, 0, intercomm);
    
        MPI_Send(&temperatures[i],1, MPI_FLOAT, i, 0, intercomm);
        printf("Pere           : Envoi vers % d.\n", i);
       
	/* MPI_Recv(&compteur, 1, MPI_INT, i, 0, intercomm, &etat);
        printf("Pere: Reception de % d.\n", i);*/
    }

    // Envoi synchrone au coordinateur
    // PHASE D'INITIALISATION FINIE
    MPI_Send(&compteur,1, MPI_INT, i, 0, intercomm);
    printf("Pere           : Envoi vers  le coordinateur % d.\n", NBPROCESS);

    // Le pere interprete la fin du programme*/
    printf("Pere : Fin.\n");
    MPI_Finalize();
    return 0;


}
